home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_include / ASM-SPAR.{_A / SPINLOCK.H < prev    next >
C/C++ Source or Header  |  1999-09-17  |  11KB  |  375 lines

  1. /* spinlock.h: 64-bit Sparc spinlock support.
  2.  *
  3.  * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
  4.  */
  5.  
  6. #ifndef __SPARC64_SPINLOCK_H
  7. #define __SPARC64_SPINLOCK_H
  8.  
  9. #ifndef __ASSEMBLY__
  10.  
  11. #ifndef __SMP__
  12.  
  13. typedef unsigned char spinlock_t;
  14. #define SPIN_LOCK_UNLOCKED 0
  15.  
  16. #define spin_lock_init(lock)    do { } while(0)
  17. #define spin_lock(lock)        do { } while(0)
  18. #define spin_trylock(lock)    do { } while(0)
  19. #define spin_unlock_wait(lock)    do { } while(0)
  20. #define spin_unlock(lock)    do { } while(0)
  21. #define spin_lock_irq(lock)    cli()
  22. #define spin_unlock_irq(lock)    sti()
  23.  
  24. #define spin_lock_irqsave(lock, flags)        save_and_cli(flags)
  25. #define spin_unlock_irqrestore(lock, flags)    restore_flags(flags)
  26.  
  27. /*
  28.  * Read-write spinlocks, allowing multiple readers
  29.  * but only one writer.
  30.  *
  31.  * NOTE! it is quite common to have readers in interrupts
  32.  * but no interrupt writers. For those circumstances we
  33.  * can "mix" irq-safe locks - any writer needs to get a
  34.  * irq-safe write-lock, but readers can get non-irqsafe
  35.  * read-locks.
  36.  */
  37. typedef unsigned long rwlock_t;
  38. #define RW_LOCK_UNLOCKED (rwlock_t) { 0 }
  39.  
  40. #define read_lock(lock)        do { } while(0)
  41. #define read_unlock(lock)    do { } while(0)
  42. #define write_lock(lock)    do { } while(0)
  43. #define write_unlock(lock)    do { } while(0)
  44. #define read_lock_irq(lock)    cli()
  45. #define read_unlock_irq(lock)    sti()
  46. #define write_lock_irq(lock)    cli()
  47. #define write_unlock_irq(lock)    sti()
  48.  
  49. #define read_lock_irqsave(lock, flags)        save_and_cli(flags)
  50. #define read_unlock_irqrestore(lock, flags)    restore_flags(flags)
  51. #define write_lock_irqsave(lock, flags)        save_and_cli(flags)
  52. #define write_unlock_irqrestore(lock, flags)    restore_flags(flags)
  53.  
  54. #else /* !(__SMP__) */
  55.  
  56. /* To get debugging spinlocks which detect and catch
  57.  * deadlock situations, set DEBUG_SPINLOCKS in the sparc64
  58.  * specific makefile and rebuild your kernel.
  59.  */
  60.  
  61. /* All of these locking primitives are expected to work properly
  62.  * even in an RMO memory model, which currently is what the kernel
  63.  * runs in.
  64.  *
  65.  * There is another issue.  Because we play games to save cycles
  66.  * in the non-contention case, we need to be extra careful about
  67.  * branch targets into the "spinning" code.  They live in their
  68.  * own section, but the newer V9 branches have a shorter range
  69.  * than the traditional 32-bit sparc branch variants.  The rule
  70.  * is that the branches that go into and out of the spinner sections
  71.  * must be pre-V9 branches.
  72.  */
  73.  
  74. #ifndef SPIN_LOCK_DEBUG
  75.  
  76. typedef unsigned char spinlock_t;
  77. #define SPIN_LOCK_UNLOCKED    0
  78.  
  79. #define spin_lock_init(lock)    (*((unsigned char *)(lock)) = 0)
  80. #define spin_is_locked(lock)    (*((volatile unsigned char *)(lock)) != 0)
  81.  
  82. #define spin_unlock_wait(lock)    \
  83. do {    membar("#LoadLoad");    \
  84. } while(*((volatile unsigned char *)lock))
  85.  
  86. extern __inline__ void spin_lock(spinlock_t *lock)
  87. {
  88.     __asm__ __volatile__("
  89. 1:    ldstub        [%0], %%g7
  90.     brnz,pn        %%g7, 2f
  91.      membar        #StoreLoad | #StoreStore
  92.     .subsection    2
  93. 2:    ldub        [%0], %%g7
  94.     brnz,pt        %%g7, 2b
  95.      membar        #LoadLoad
  96.     b,a,pt        %%xcc, 1b
  97.     .previous
  98. "    : /* no outputs */
  99.     : "r" (lock)
  100.     : "g7", "memory");
  101. }
  102.  
  103. extern __inline__ int spin_trylock(spinlock_t *lock)
  104. {
  105.     unsigned int result;
  106.     __asm__ __volatile__("ldstub [%1], %0\n\t"
  107.                  "membar #StoreLoad | #StoreStore"
  108.                  : "=r" (result)
  109.                  : "r" (lock)
  110.                  : "memory");
  111.     return (result == 0);
  112. }
  113.  
  114. extern __inline__ void spin_unlock(spinlock_t *lock)
  115. {
  116.     __asm__ __volatile__("membar    #StoreStore | #LoadStore\n\t"
  117.                  "stb    %%g0, [%0]\n\t"
  118.                  : /* No outputs */
  119.                  : "r" (lock)
  120.                  : "memory");
  121. }
  122.  
  123. extern __inline__ void spin_lock_irq(spinlock_t *lock)
  124. {
  125.     __asm__ __volatile__("
  126.     wrpr        %%g0, 15, %%pil
  127. 1:    ldstub        [%0], %%g7
  128.     brnz,pn        %%g7, 2f
  129.      membar        #StoreLoad | #StoreStore
  130.     .subsection    2
  131. 2:    ldub        [%0], %%g7
  132.     brnz,pt        %%g7, 2b
  133.      membar        #LoadLoad
  134.     b,a,pt        %%xcc, 1b
  135.     .previous
  136. "    : /* no outputs */
  137.     : "r" (lock)
  138.     : "g7", "memory");
  139. }
  140.  
  141. extern __inline__ void spin_unlock_irq(spinlock_t *lock)
  142. {
  143.     __asm__ __volatile__("
  144.     membar        #StoreStore | #LoadStore
  145.     stb        %%g0, [%0]
  146.     wrpr        %%g0, 0x0, %%pil
  147. "    : /* no outputs */
  148.     : "r" (lock)
  149.     : "memory");
  150. }
  151.  
  152. #define spin_lock_irqsave(__lock, flags)            \
  153. do {    register spinlock_t *__lp asm("g1");            \
  154.     __lp = (__lock);                    \
  155.     __asm__ __volatile__(                    \
  156.     "\n    rdpr        %%pil, %0\n"            \
  157.     "    wrpr        %%g0, 15, %%pil\n"        \
  158.     "1:    ldstub        [%1], %%g7\n"            \
  159.     "    brnz,pn        %%g7, 2f\n"            \
  160.     "     membar        #StoreLoad | #StoreStore\n"    \
  161.     "    .subsection    2\n"                \
  162.     "2:    ldub        [%1], %%g7\n"            \
  163.     "    brnz,pt        %%g7, 2b\n"            \
  164.     "     membar        #LoadLoad\n"            \
  165.     "    b,a,pt        %%xcc, 1b\n"            \
  166.     "    .previous\n"                    \
  167.     : "=&r" (flags)                        \
  168.     : "r" (__lp)                        \
  169.     : "g7", "memory");                    \
  170. } while(0)
  171.  
  172. extern __inline__ void spin_unlock_irqrestore(spinlock_t *lock, unsigned long flags)
  173. {
  174.     __asm__ __volatile__("
  175.     membar        #StoreStore | #LoadStore
  176.     stb        %%g0, [%0]
  177.     wrpr        %1, 0x0, %%pil
  178. "    : /* no outputs */
  179.     : "r" (lock), "r" (flags)
  180.     : "memory");
  181. }
  182.  
  183. #else /* !(SPIN_LOCK_DEBUG) */
  184.  
  185. typedef struct {
  186.     unsigned char lock;
  187.     unsigned int owner_pc, owner_cpu;
  188. } spinlock_t;
  189. #define SPIN_LOCK_UNLOCKED (spinlock_t) { 0, 0, NO_PROC_ID }
  190. #define spin_lock_init(__lock)    \
  191. do {    (__lock)->lock = 0; \
  192.     (__lock)->owner_pc = 0; \
  193.     (__lock)->owner_cpu = NO_PROC_ID; \
  194. } while(0)
  195. #define spin_is_locked(__lock)    (*((volatile unsigned char *)(&((__lock)->lock))) != 0)
  196. #define spin_unlock_wait(__lock)    \
  197. do { \
  198.     membar("#LoadLoad"); \
  199. } while(*((volatile unsigned char *)(&((__lock)->lock))))
  200.  
  201. extern void _do_spin_lock (spinlock_t *lock, char *str);
  202. extern void _do_spin_unlock (spinlock_t *lock);
  203. extern int _spin_trylock (spinlock_t *lock);
  204.  
  205. #define spin_trylock(lp)    _spin_trylock(lp)
  206. #define spin_lock(lock)        _do_spin_lock(lock, "spin_lock")
  207. #define spin_lock_irq(lock)    do { __cli(); _do_spin_lock(lock, "spin_lock_irq"); } while(0)
  208. #define spin_lock_irqsave(lock, flags) do { __save_and_cli(flags); _do_spin_lock(lock, "spin_lock_irqsave"); } while(0)
  209. #define spin_unlock(lock)    _do_spin_unlock(lock)
  210. #define spin_unlock_irq(lock)    do { _do_spin_unlock(lock); __sti(); } while(0)
  211. #define spin_unlock_irqrestore(lock, flags) do { _do_spin_unlock(lock); __restore_flags(flags); } while(0)
  212.  
  213. #endif /* SPIN_LOCK_DEBUG */
  214.  
  215. /* Multi-reader locks, these are much saner than the 32-bit Sparc ones... */
  216.  
  217. #ifndef SPIN_LOCK_DEBUG
  218.  
  219. typedef unsigned long rwlock_t;
  220. #define RW_LOCK_UNLOCKED    0
  221.  
  222. extern __inline__ void read_lock(rwlock_t *rw)
  223. {
  224.     __asm__ __volatile__("
  225. 1:    ldx        [%0], %%g5
  226.     brlz,pn        %%g5, 2f
  227. 4:     add        %%g5, 1, %%g7
  228.     casx        [%0], %%g5, %%g7
  229.     cmp        %%g5, %%g7
  230.     bne,pn        %%xcc, 1b
  231.      membar        #StoreLoad | #StoreStore
  232.     .subsection    2
  233. 2:    ldx        [%0], %%g5
  234.     brlz,pt        %%g5, 2b
  235.      membar        #LoadLoad
  236.     b,a,pt        %%xcc, 4b
  237.     .previous
  238. "    : /* no outputs */
  239.     : "r" (rw)
  240.     : "g5", "g7", "cc", "memory");
  241. }
  242.  
  243. extern __inline__ void read_unlock(rwlock_t *rw)
  244. {
  245.     __asm__ __volatile__("
  246. 1:    ldx        [%0], %%g5
  247.     sub        %%g5, 1, %%g7
  248.     casx        [%0], %%g5, %%g7
  249.     cmp        %%g5, %%g7
  250.     bne,pn        %%xcc, 1b
  251.      membar        #StoreLoad | #StoreStore
  252. "    : /* no outputs */
  253.     : "r" (rw)
  254.     : "g5", "g7", "cc", "memory");
  255. }
  256.  
  257. extern __inline__ void write_lock(rwlock_t *rw)
  258. {
  259.     __asm__ __volatile__("
  260.     sethi        %%uhi(0x8000000000000000), %%g3
  261.     sllx        %%g3, 32, %%g3
  262. 1:    ldx        [%0], %%g5
  263.     brlz,pn        %%g5, 5f
  264. 4:     or        %%g5, %%g3, %%g7
  265.     casx        [%0], %%g5, %%g7
  266.     cmp        %%g5, %%g7
  267.     bne,pn        %%xcc, 1b
  268.      andncc        %%g7, %%g3, %%g0
  269.     bne,pn        %%xcc, 7f
  270.      membar        #StoreLoad | #StoreStore
  271.     .subsection    2
  272. 7:    ldx        [%0], %%g5
  273.     andn        %%g5, %%g3, %%g7
  274.     casx        [%0], %%g5, %%g7
  275.     cmp        %%g5, %%g7
  276.     bne,pn        %%xcc, 7b
  277.      membar        #StoreLoad | #StoreStore
  278. 5:    ldx        [%0], %%g5
  279.     brnz,pt        %%g5, 5b
  280.      membar        #LoadLoad
  281.     b,a,pt        %%xcc, 4b
  282.     .previous
  283. "    : /* no outputs */
  284.     : "r" (rw)
  285.     : "g3", "g5", "g7", "memory", "cc");
  286. }
  287.  
  288. extern __inline__ void write_unlock(rwlock_t *rw)
  289. {
  290.     __asm__ __volatile__("
  291.     sethi        %%uhi(0x8000000000000000), %%g3
  292.     sllx        %%g3, 32, %%g3
  293. 1:    ldx        [%0], %%g5
  294.     andn        %%g5, %%g3, %%g7
  295.     casx        [%0], %%g5, %%g7
  296.     cmp        %%g5, %%g7
  297.     bne,pn        %%xcc, 1b
  298.      membar        #StoreLoad | #StoreStore
  299. "    : /* no outputs */
  300.     : "r" (rw)
  301.     : "g3", "g5", "g7", "memory", "cc");
  302. }
  303.  
  304. #define read_lock_irq(lock)    do { __cli(); read_lock(lock); } while (0)
  305. #define read_unlock_irq(lock)    do { read_unlock(lock); __sti(); } while (0)
  306. #define write_lock_irq(lock)    do { __cli(); write_lock(lock); } while (0)
  307. #define write_unlock_irq(lock)    do { write_unlock(lock); __sti(); } while (0)
  308.  
  309. #define read_lock_irqsave(lock, flags)    \
  310.     do { __save_and_cli(flags); read_lock(lock); } while (0)
  311. #define read_unlock_irqrestore(lock, flags) \
  312.     do { read_unlock(lock); __restore_flags(flags); } while (0)
  313. #define write_lock_irqsave(lock, flags)    \
  314.     do { __save_and_cli(flags); write_lock(lock); } while (0)
  315. #define write_unlock_irqrestore(lock, flags) \
  316.     do { write_unlock(lock); __restore_flags(flags); } while (0)
  317.  
  318. #else /* !(SPIN_LOCK_DEBUG) */
  319.  
  320. typedef struct {
  321.     unsigned long lock;
  322.     unsigned int writer_pc, writer_cpu;
  323.     unsigned int reader_pc[4];
  324. } rwlock_t;
  325. #define RW_LOCK_UNLOCKED    (rwlock_t) { 0, 0, NO_PROC_ID, { 0, 0, 0, 0 } }
  326.  
  327. extern void _do_read_lock(rwlock_t *rw, char *str);
  328. extern void _do_read_unlock(rwlock_t *rw, char *str);
  329. extern void _do_write_lock(rwlock_t *rw, char *str);
  330. extern void _do_write_unlock(rwlock_t *rw);
  331.  
  332. #define read_lock(lock)    \
  333. do {    unsigned long flags; \
  334.     __save_and_cli(flags); \
  335.     _do_read_lock(lock, "read_lock"); \
  336.     __restore_flags(flags); \
  337. } while(0)
  338. #define read_lock_irq(lock)    do { __cli(); _do_read_lock(lock, "read_lock_irq"); } while(0)
  339. #define read_lock_irqsave(lock, flags) do { __save_and_cli(flags); _do_read_lock(lock, "read_lock_irqsave"); } while(0)
  340.  
  341. #define read_unlock(lock) \
  342. do {    unsigned long flags; \
  343.     __save_and_cli(flags); \
  344.     _do_read_unlock(lock, "read_unlock"); \
  345.     __restore_flags(flags); \
  346. } while(0)
  347. #define read_unlock_irq(lock)    do { _do_read_unlock(lock, "read_unlock_irq"); __sti() } while(0)
  348. #define read_unlock_irqrestore(lock, flags) do { _do_read_unlock(lock, "read_unlock_irqrestore"); __restore_flags(flags); } while(0)
  349.  
  350. #define write_lock(lock) \
  351. do {    unsigned long flags; \
  352.     __save_and_cli(flags); \
  353.     _do_write_lock(lock, "write_lock"); \
  354.     __restore_flags(flags); \
  355. } while(0)
  356. #define write_lock_irq(lock)    do { __cli(); _do_write_lock(lock, "write_lock_irq"); } while(0)
  357. #define write_lock_irqsave(lock, flags) do { __save_and_cli(flags); _do_write_lock(lock, "write_lock_irqsave"); } while(0)
  358.  
  359. #define write_unlock(lock) \
  360. do {    unsigned long flags; \
  361.     __save_and_cli(flags); \
  362.     _do_write_unlock(lock); \
  363.     __restore_flags(flags); \
  364. } while(0)
  365. #define write_unlock_irq(lock)    do { _do_write_unlock(lock); __sti(); } while(0)
  366. #define write_unlock_irqrestore(lock, flags) do { _do_write_unlock(lock); __restore_flags(flags); } while(0)
  367.  
  368. #endif /* SPIN_LOCK_DEBUG */
  369.  
  370. #endif /* __SMP__ */
  371.  
  372. #endif /* !(__ASSEMBLY__) */
  373.  
  374. #endif /* !(__SPARC64_SPIN%0_H) */
  375.